home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
telecomm
/
sticpsrc.lzh
/
SOURCE.ARC
/
PERSIST.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-02
|
4KB
|
177 lines
/* automatic persistence setting for ax.25 interfaces */
#include "global.h"
#include "ax25.h"
#include "iface.h"
#include "persist.h"
#include "timer.h"
static struct persist *pblk; /* list of persistence cb's */
static struct timer p_timer;
static void tick_ptimer();
extern char nospace[],notax25[];
/* set/show automatic persistence calculation parameters */
int
dopersist(argc,argv)
int argc;
char *argv[];
{
register struct persist *pp;
struct interface *ifp;
if (argc == 1){ /* no args - show parms */
printf("IF Users P P0 Pmin Pmax Tinc Tmax\n");
for (pp = pblk; pp != NULLPERSIST; pp = pp->next)
printf("%-6s%5d%5d%5d%6d%6d%6d%6d\n",pp->iface->name,
pp->n_users,pp->p,pp->p0,pp->p_min,pp->p_max,
pp->pt_incr * PT_INTER,pp->pt_max * PT_INTER);
return 0;
}
if ((ifp = ifunit(argv[1])) == NULLIF)
return 1;
if (!(ifp->flags & IF_AX25)){
printf(notax25,argv[1]);
return 1;
}
stop_timer(&p_timer);
for (pp = pblk; pp != NULLPERSIST; pp = pp->next)
if (pp->iface == ifp) /* lookup by interface */
break;
if (pp == NULLPERSIST){ /* if not in list? */
if ((pp = (struct persist *) calloc(1,sizeof(struct persist))) == NULLPERSIST){
printf(nospace);
if (pblk != NULLPERSIST)
start_timer(&p_timer);
return 1;
}
if ((pp->next = pblk) != NULLPERSIST)
pp->next->prev = pp;
pblk = pp;
pp->iface = ifp;
pp->p0 = P0;
pp->p_min = P_MIN;
pp->p_max = pp->p = P_MAX;
pp->pt_incr = PT_INCR;
pp->pt_max = PT_MAX;
}
/* set control values, delete cb when p0 value is 0 (or "off") */
if (argc > 2)
if ((pp->p0 = atoi(argv[2])) == 0){
if (pp->prev != NULLPERSIST)
pp->prev->next = pp->next;
else
pblk = pp->next;
if (pp->next != NULLPERSIST)
pp->next->prev = pp->prev;
free(pp);
}
if (argc > 3)
pp->p_min = atoi(argv[3]);
if (argc > 4)
pp->p_max = atoi(argv[4]);
if (argc > 5)
pp->pt_incr = atoi(argv[5]) / PT_INTER;
if (argc > 6)
pp->pt_max = atoi(argv[6]) / PT_INTER;
/* (re)start the timer only if any persistence cb's left */
if (pblk != NULLPERSIST){
p_timer.start = SEC2TICK(PT_INTER);
p_timer.func = tick_ptimer;
tick_ptimer();
}
return 0;
}
/* update the "number of users" for an interface when a callsign is heard */
/* the ssid is not considered significant */
int
upd_nusers (ifp,call)
struct interface *ifp;
register unsigned char *call;
{
register struct persist *pp;
register unsigned hashval;
register int i;
for (pp = pblk; pp != NULLPERSIST; pp = pp->next)
if (pp->iface == ifp) /* lookup by interface */
break;
if (pp == NULLPERSIST) /* if not in list? */
return -1; /* return soft failure */
hashval = 0;
for (i = 0; i < ALEN; i++) /* scan callsign (not SSID) */
hashval = (hashval << 1) ^ (*call++ & 0xfe);
hashval %= (unsigned) SLOTS;
if ((pp->heard[hashval] += pp->pt_incr) > pp->pt_max)
pp->heard[hashval] = pp->pt_max;
return 0; /* ok */
}
/* tick the "automatic persistence" timer, decrementing the timers and */
/* re-computing the number of users on each channel. when changed, set */
/* the persistence value for that channel. */
static void
tick_ptimer ()
{
register struct persist *pp;
register unsigned i,n_users,p;
static char *argv[3] = {"2","###",NULLCHAR};
for (pp = pblk; pp != NULLPERSIST; pp = pp->next){
n_users = 0;
for (i = 0; i < SLOTS; i++)
if (pp->heard[i]){
pp->heard[i]--;
n_users++; /* count the active users */
}
if ((pp->n_users = n_users) == 0)
p = pp->p0;
else
p = pp->p0 / n_users;
if (p > pp->p_max) /* keep p within p_min .. p_max */
p = pp->p_max;
if (p < pp->p_min)
p = pp->p_min;
if (pp->p != p){ /* a change in p value? */
sprintf(argv[1],"%d",pp->p = p); /* convert to string */
if (pp->iface->ioctl != NULLFP)
(*pp->iface->ioctl)(pp->iface,2,argv); /* set p value */
}
}
start_timer(&p_timer); /* restart the timer */
}